package com.yds.ydsdatasetbackend.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yds.ydsdatasetbackend.annotation.AuthCheck;
import com.yds.ydsdatasetbackend.common.BaseResponse;
import com.yds.ydsdatasetbackend.common.DeleteRequest;
import com.yds.ydsdatasetbackend.common.ResultUtils;
import com.yds.ydsdatasetbackend.constant.UserConstant;
import com.yds.ydsdatasetbackend.exception.BusinessException;
import com.yds.ydsdatasetbackend.exception.ErrorCode;
import com.yds.ydsdatasetbackend.exception.ThrowUtils;
import com.yds.ydsdatasetbackend.model.dto.file.predict.*;

import com.yds.ydsdatasetbackend.model.dto.file.train.FileTrainQueryRequest;
import com.yds.ydsdatasetbackend.model.entity.FilePredict;
import com.yds.ydsdatasetbackend.model.entity.FileTrain;
import com.yds.ydsdatasetbackend.model.entity.FileVariables;
import com.yds.ydsdatasetbackend.model.entity.User;
import com.yds.ydsdatasetbackend.model.vo.FilePredictVO;
import com.yds.ydsdatasetbackend.model.vo.FilePredictVariables;
import com.yds.ydsdatasetbackend.model.vo.FileTrainVO;
import com.yds.ydsdatasetbackend.service.FilePredictService;
import com.yds.ydsdatasetbackend.service.FileTrainService;
import com.yds.ydsdatasetbackend.service.FileVariablesService;
import com.yds.ydsdatasetbackend.service.UserService;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/file/predict")
public class FilePredictController {

    @Resource
    private FilePredictService filePredictService;

    @Resource
    @Lazy
    private FileTrainService fileTrainService;

    @Resource
    private UserService userService;

    @Resource
    private FileVariablesService fileVariablesService;


    /**
     * 添加文件预测
     */
    @PostMapping("/add")
    @AuthCheck(mustRole = UserConstant.USER_LOGIN_STATE)
    public BaseResponse<Boolean> addFilePredict(@RequestBody FilePredictAddRequest filePredictAddRequest, HttpServletRequest request) {
        if (filePredictAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        filePredictService.addFilePredict(filePredictAddRequest, loginUser);
        return ResultUtils.success(true);
    }

    /**
     * 根据 id 获取文件（仅管理员可用）
     */
    @GetMapping("/get")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<FilePredict> getFilePredictById(long id, HttpServletRequest request) {
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        // 查询数据库
        FilePredict filePredict = filePredictService.getById(id);
        ThrowUtils.throwIf(filePredict == null, ErrorCode.NOT_FOUND_ERROR);
        // 获取封装类
        return ResultUtils.success(filePredict);
    }

    /**
     * 根据 id 获取文件（封装类）
     */
    @GetMapping("/get/vo")
    @AuthCheck(mustRole = UserConstant.USER_LOGIN_STATE)
    public BaseResponse<FilePredictVO> getFilePredictVOById(long id, HttpServletRequest request) {
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        // 查询数据库
        FilePredict filePredict = filePredictService.getById(id);
        ThrowUtils.throwIf(filePredict == null, ErrorCode.NOT_FOUND_ERROR);
        FilePredictVO filePredictVO = filePredictService.getFilePredictVO(filePredict, request);
//        fileVO.setPermissionList(permissionList);
        // 获取封装类
        return ResultUtils.success(filePredictVO);
    }

    /**
     * 编辑文件
     */
    @PostMapping("/edit")
    @AuthCheck(mustRole = UserConstant.USER_LOGIN_STATE)
    public BaseResponse<Boolean> editFilePredict(@RequestBody FilePredictEditRequest filePredictEditRequest, HttpServletRequest request) {
        if (filePredictEditRequest == null || filePredictEditRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        filePredictService.editFilePredict(filePredictEditRequest, loginUser);
        return ResultUtils.success(true);
    }

    /**
     * 删除文件
     */
    @PostMapping("/delete")
    @AuthCheck(mustRole = UserConstant.USER_LOGIN_STATE)
    public BaseResponse<Boolean> deleteFilePredict(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        filePredictService.deleteFilePredict(deleteRequest.getId(), loginUser);
        return ResultUtils.success(true);
    }

    /**
     * 分页获取文件列表（仅管理员可用）
     */
    @PostMapping("/list/page")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<FilePredict>> listFilePredictByPage(@RequestBody FilePredictQueryRequest filePredictQueryRequest, HttpServletRequest request) {

        long current = filePredictQueryRequest.getCurrent();
        long size = filePredictQueryRequest.getPageSize();
        // 查询数据库
        Page<FilePredict> filePredictPage = filePredictService.page(new Page<>(current, size),
                filePredictService.getQueryWrapper(filePredictQueryRequest));
        return ResultUtils.success(filePredictPage);
    }

    @PostMapping("/list/page/vo")
    @AuthCheck(mustRole = UserConstant.USER_LOGIN_STATE)
    public BaseResponse<Page<FilePredictVO>> listFilePredictVOByPage(@RequestBody FilePredictQueryRequest filePredictQueryRequest,
                                                                 HttpServletRequest request) {
        // 进行校验，只有对应用户或者管理员才能查看对应信息
        FileTrain fileTrain = fileTrainService.getById(filePredictQueryRequest.getTrainId());
        User loginUser = userService.getLoginUser(request);
        fileTrainService.checkFileTrainAuth(loginUser, fileTrain);

        long current = filePredictQueryRequest.getCurrent();
        long size = filePredictQueryRequest.getPageSize();
        // 限制爬虫
        ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);

        // 查询数据库
        Page<FilePredict> filePredictPage = filePredictService.page(new Page<>(current, size),
                filePredictService.getQueryWrapper(filePredictQueryRequest));
        // 获取封装类
        return ResultUtils.success(filePredictService.getFilePredictVOPage(filePredictPage, request));
    }

    @PostMapping("/get/variables")
    public BaseResponse<FilePredictVariables> getFileVariablesList(@RequestBody FilePredictGetVariablesRequest filePredictGetVariablesRequest) {
        if (filePredictGetVariablesRequest == null || filePredictGetVariablesRequest.getTrainId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long trainId = filePredictGetVariablesRequest.getTrainId();
        FileTrain fileTrain = fileTrainService.getById(trainId);
        Long fileId = fileTrain.getFileId();


        List<Long> featureList = JSONUtil.toList(fileTrain.getSelectFeatures(), Long.class);
        List<Long> targetList = JSONUtil.toList(fileTrain.getSelectTargets(), Long.class);

        Map<Long, List<FileVariables>> columnVariablesListMap = fileVariablesService.lambdaQuery()
                .eq(FileVariables::getFileId,fileId).list().stream().collect(Collectors.groupingBy(FileVariables::getColumnNumber));

        List<FilePredictOutputParams> featureOutputList = new ArrayList<>();
        for (Long featureColumn : featureList) {
            featureColumn ++ ;
            FilePredictOutputParams filePredictOutputParams = new FilePredictOutputParams();
            filePredictOutputParams.setColumnNumber(featureColumn);
            // 变量数据表的collumn是从1开始，而其余从0开始
            if(columnVariablesListMap.containsKey(featureColumn)){
                filePredictOutputParams.setVariablesName(columnVariablesListMap.get(featureColumn).get(0).getName());
            }
            featureOutputList.add(filePredictOutputParams);
        }

        List<FilePredictOutputParams> targetOutputList = new ArrayList<>();
        for (Long targetColumn : targetList) {
            targetColumn ++ ;
            FilePredictOutputParams filePredictOutputParams = new FilePredictOutputParams();
            filePredictOutputParams.setColumnNumber(targetColumn);
            // 变量数据表的collumn是从1开始，而其余从0开始
            if(columnVariablesListMap.containsKey(targetColumn)){
                filePredictOutputParams.setVariablesName(columnVariablesListMap.get(targetColumn).get(0).getName());
            }
            targetOutputList.add(filePredictOutputParams);
        }

        FilePredictVariables filePredictVariables = new FilePredictVariables();
        filePredictVariables.setFeatureOutputParamsList(featureOutputList);
        filePredictVariables.setTargetOutputParamsList(targetOutputList);
        return ResultUtils.success(filePredictVariables);
    }

}
